
#include <iostream>
using namespace std;
class Point
{
    friend ostream& operator<<(ostream& out, const Point& p);
public:
    Point(double x = 0, double y = 0);
    Point(const Point& p);
    ~Point();

    Point& operator=(const Point& p);
    double operator[](int index);
    Point& operator++();    // 前置 ++
    Point operator++(int);  // 后置 ++
    Point& operator--();    // 前置 --
    Point operator--(int);  // 后置 --
    Point& operator-();     // 负号
    Point operator+(const Point& p);
private:
    double x;
    double y;
};

Point::Point(double x, double y)
    : x(x)
    , y(y)
{
    cout << "Point(double x, double y)" << endl;
}

Point::Point(const Point& p)
    : x(p.x)
    , y(p.y)
{
    cout << "Point::Point(const Point& p)" << endl;
}

Point::~Point()
{
    cout << "~Point()" << endl;
}

Point& Point::operator=(const Point& p)
{
    cout << "operator=(const Point& p)" << endl;
    this->x = p.x;
    this->y = p.y;
    return *this;
}

double Point::operator[](int index)
{
    if(index < 0 || index > 1)
        throw out_of_range("index out of range, index range in [0, 1].");
    if(0 == index)
        return this->x;
    if(1 == index)
        return this->y;
}

Point& Point::operator++()
{
    ++this->x;
    ++this->y;
    return *this;
}

Point Point::operator++(int)
{
    Point temp(*this);
    operator++();
    return temp;
}

Point& Point::operator--()
{
    --this->x;
    --this->y;
    return *this;
}

Point Point::operator--(int)
{
    Point temp(*this);
    operator--();
    return temp;
}

Point& Point::operator-()
{
    this->x = -this->x;
    this->y = -this->y;
    return *this;
}

Point Point::operator+(const Point& p)
{
    // 在运算符重载函数中构造一个临时对象并返回一个对象。

    // 由于临时对象在函数内有效，出了该函数后将再次通过拷贝构造一个临时对象。
    // Point temp;
    // temp.x = this->x + p.x;
    // temp.y = this->y + p.y;
    // return temp;
    return Point(this->x + p.x, this->y + p.y);
}

ostream& operator<<(ostream& out, const Point& p)
{
    out << "Point(" << p.x << ", " << p.y << ")" << endl;
    return out;
}

int main()
{
    // Point p(3, 4);
    // cout << p;

    // Point p2;
    // // 调用赋值运算符
    // p2 = p;

    // cout << p2[0] << ", " << p2[1] << endl;

    // try
    // {
    //     cout << p2[2] << endl;
    // }
    // catch(const std::exception& e)
    // {
    //     std::cerr << e.what() << '\n';
    // }

    Point p1(3, 4), p2(5, 6);
    // cout << p1;
    Point p3;
    p3 = p1 + p2;

    // // 前置 ++
    // cout << "前置 ++: " << ++p1;

    // // 后置 ++
    // cout << "后置 ++: " << p1++;
    // cout << "后置 ++: " << p1;


    // // 前置 --
    // cout << "前置 --: " << --p1;

    // // 后置 --
    // cout << "后置 --: " << p1--;
    // cout << "后置 --: " << p1;


    // // 负号
    // cout << "负号: " << -p1;

    return 0;
}